//
//  main.cpp
//  sad
//
//  Created by Christopher Kemsley on 1/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//




#include "systemc.h"


#include "ModuleFactory.hpp"
#include "PubSub.hpp"
#include "URL.hpp"

#include "DelayedBinding.hpp"

#include "URL.hpp"
#include "Exception.hpp"


#include "Settings.hpp"
#include "Codec.hpp"
#include "Log.hpp"

#include "IAAny.hpp"
#include <typeinfo>


struct	MainSettings : public Settings
{
	URL				logConfiguration ;
	ModelVariant	module ;
	SCInterval		runDuration ;
	
	MainSettings ( std::string const & name )
	:	Settings (name)
	,	logConfiguration	( "log.config.xml" )
	,	module				(  )
	,	runDuration			( 1 , kSCIntervalSeconds )
		{
		add ( "logConfigURL" , logConfiguration ) ;
		add ( "module" , module ) ;
		add ( "runDuration" , runDuration ) ;
		}
	
	virtual void		validate ()
		{
		if ( logConfiguration.path().size() == 0 )
			std::cout << "Warning: no log settings. By default, only errors will be shown\n" ;
		}
} ;










#include "URLTest.hpp"

int sc_main (int argc, char * argv[]) {
	try
		{
		sc_set_stop_mode(SC_STOP_IMMEDIATE) ;
		
		
		URL		mainURL		( argc>1 ? argv[1] : "file:./main.xml" ) ;
		
		
		
		
		/* Set the PWD as the baseURL (temporarily) */
		
		char	buffer [500] ;
		getcwd ( buffer , 500 ) ;
		
		URL		pwdURL		( buffer , true ) ;
		
		if ( ! pwdURL.isAbsolute() )
			{
			std::cout << "Fatal error: PWD wasn't absolute!\n\n" ;
			return -1 ;
			}
		
		pwdURL.makeBaseURL() ;
		
		
		
		
		
		
		/* Update the mainURL again and make the baseURL to be relative to it */
		
		URL		mainBase	=	mainURL . directoryURL() ;
		mainBase			=	mainBase . absoluteURL() ;
		Log::notice("main") << "Base URL: " << mainBase ;
		mainBase.makeBaseURL() ;
		
		mainURL		=	URL ( mainURL.filename() ) ;
		
		
		
		
		
		
		MainSettings	appInfo ( "Main") ;
		
		if ( Codec :: decode<URL,Settings> ( mainURL , appInfo ) )
			{
			Log :: loadConfiguration	( appInfo.logConfiguration ) ;
			
			Log::notice("main") << "Root module: " << appInfo.module ;
			Log::notice("main") << "Run duration: " << appInfo.runDuration ;
			
			Model	*	root	=	ModuleFactory :: create ( appInfo.module ) ;
			
			if ( root == 0 )
				ThrowException ( "main" , "Failed to create root model. URL = " << appInfo.module , __FILE__,__LINE__ ) ;
			
			DelayedBinding :: runAll () ;
			
			sc_start ( appInfo.runDuration ) ;
			
			Log::notice("main") << "Simulation ended @ " << SCCurrentTime() << "\n" ;
			
			Log::flush() ;
			
			delete root ;
			}
		else
			{
			Log::error("main") << "Application info not found. Either (1) specify a main.xml file ('executable /path/to/main.xml') or (2) have 'main.xml' in the PWD\n\n" ;
			}
		}
	
	
	
	catch ( Exception & e )
		{
		Log :: logException ( e ) ;
		std::cout << "\n\n\n***** Exiting due to exception *****\n" ;
		return -1 ;
		}
	catch ( std::exception & e )
		{
		Log :: logException ( Exception("Unknown",e.what(),__FILE__,__LINE__) ) ;
		std::cout << "\n\n\n***** Exiting due to exception *****\n" ;
		return -1 ;
		}
	catch ( ... )
		{
		Log :: logException ( Exception("Unknown","An unknown exception occurred",__FILE__,__LINE__) ) ;
		std::cout << "\n\n\n***** Exiting due to exception *****\n" ;
		return -1 ;
		}
	
	
	
	Log::flush() ;
	
	
	
    return 0;
}



